package com.yunkeji.api.gift.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yunkeji.api.common.service.SysParamService;
import com.yunkeji.api.gift.service.GiftService;
import com.yunkeji.api.gift.vo.GiftInfoVo;
import com.yunkeji.api.gift.vo.MsgGift;
import com.yunkeji.api.pay.bo.SendGiftBo;
import com.yunkeji.api.user.mapper.ApiAppUserMapper;
import com.yunkeji.api.user.mapper.ApiGiftReceiveMapper;
import com.yunkeji.common.constant.SysConfigConsts;
import com.yunkeji.common.core.domain.dto.PayLogDTO;
import com.yunkeji.common.core.domain.event.PushRollingEvent;
import com.yunkeji.common.enums.app.EnableEnum;
import com.yunkeji.common.enums.app.GiftType;
import com.yunkeji.common.enums.app.PayLogTypeEnums;
import com.yunkeji.common.exception.AppServiceException;
import com.yunkeji.common.helper.LoginHelper;
import com.yunkeji.common.msg.PushMessage;
import com.yunkeji.common.msg.bo.PrivateMsg;
import com.yunkeji.dao.domain.*;
import com.yunkeji.dao.mapper.AppUserExtMapper;
import com.yunkeji.dao.mapper.AppUserWalletMapper;
import com.yunkeji.dao.mapper.GiftMapper;
import com.yunkeji.dao.mapper.GiftReceiveMapper;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * @author 老张
 */
@Slf4j
@Service
@AllArgsConstructor
public class GiftServiceImpl implements GiftService {
    private final ApiGiftReceiveMapper apiGiftReceiveMapper;
    private final GiftMapper giftMapper;
    private final GiftReceiveMapper giftReceiveMapper;
    private final AppUserWalletMapper appUserWalletMapper;
    private final ApiAppUserMapper apiAppUserMapper;
    private final AppUserExtMapper appUserExtMapper;
    private final SysParamService sysParamService;

    /**
     * 送礼物
     *
     * @author 老张
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendGift(SendGiftBo bo) {
        Gift gift = giftMapper.selectById(bo.getGiftId());
        if (gift == null
                || gift.getValidFlag().equals(EnableEnum.NO.getCode())
                || gift.getDelFlag().equals(EnableEnum.YES.getCode())) {
            throw AppServiceException.paramException("礼物异常");
        }
        AppUser recAppUser = apiAppUserMapper.selectById(bo.getRecId());
        AppUser sendAppUser = apiAppUserMapper.selectById(LoginHelper.getUserId());

        //        if (recAppUser.getSex().equals(sendAppUser.getSex())) {
        //            throw AppServiceException.paramException("暂不可为对方赠送礼物");
        //        }

        Long sendUserId = LoginHelper.getUserId();
        AppUserWallet appUserWallet = appUserWalletMapper.selectById(sendUserId);

        AppUserVip build = AppUserVip.builder().build().selectById(sendUserId);

        if (gift.getType().equals(GiftType.VIP礼物.getCode())
                && build.getCommonVipFlag().equals(EnableEnum.NO.getCode())) {
            throw AppServiceException.paramException("无法赠送会员礼物");
        }

        if ((gift.getType().equals(GiftType.亲密度礼物.getCode()))) {
            if (StrUtil.isEmpty(gift.getExtValue())) {
                throw AppServiceException.paramException("礼物参数错误");
            }
            // 亲密度礼物
            UserFocus build1 =
                    UserFocus.builder()
                            .fansUserId(LoginHelper.getUserId())
                            .focusUserId(bo.getRecId())
                            .build();
            UserFocus userFocus =
                    build1.selectOne(
                            Wrappers.lambdaQuery(UserFocus.class)
                                    .eq(UserFocus::getSortId, build1.getSortIdStr()));
            if (userFocus == null
                    || NumberUtil.isLess(
                            userFocus.getLoveValue(), new BigDecimal(gift.getExtValue()))) {
                throw AppServiceException.paramException("亲密度不足,无法赠送专属礼物,请先提升亲密度");
            }
        }

        BigDecimal sumPrice = gift.getPrice().multiply(BigDecimal.valueOf(bo.getNum()));
        if (NumberUtil.isGreater(sumPrice, appUserWallet.getGoldBalance())) {
            throw AppServiceException.goldNotEnoughException("余额不足");
        }

        GiftReceive giftRec =
                GiftReceive.builder()
                        .num(bo.getNum())
                        .giftId(gift.getId())
                        .sendUid(sendUserId)
                        .recUid(bo.getRecId())
                        .price(sumPrice)
                        .giftImg(gift.getImgUri())
                        .giftName(gift.getName())
                        .build();
        // 创建礼物接受日志
        giftReceiveMapper.insert(giftRec);
        // 扣减赠送人的金币
        Integer integer =
                apiAppUserMapper.logSubGoldBalance(
                        PayLogDTO.builder()
                                .traceId(giftRec.getId())
                                .uid(sendUserId)
                                .changeNum(sumPrice)
                                .serviceTag(
                                        "用户赠送礼物"
                                                + gift.getName()
                                                + "X"
                                                + bo.getNum()
                                                + "-接收人:"
                                                + recAppUser.getPlatformId())
                                .logType(PayLogTypeEnums.消费_赠送礼物)
                                .build());
        if (integer != 1) {
            log.error("余额不足");
            throw AppServiceException.goldNotEnoughException("余额不足,请充值后再试");
        }

        Long pid = recAppUser.getPid();
        BigDecimal earnTotal = sumPrice;
        if (pid != null) {
            // -举个例子, 比如礼物是100 发送方扣100,接收方得90,邀请方得10,是吗 -确认一下呢
            // - Monsters(sudo rm -rf)  是的呐
            BigDecimal giftRate =
                    new BigDecimal(sysParamService.selectConfigByKey(SysConfigConsts.邀请礼物奖励));
            // 收益比例
            BigDecimal rate = giftRate.divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN);
            // 收益向下取整
            BigDecimal earn = sumPrice.multiply(rate).setScale(0, RoundingMode.DOWN);
            // 邀请人加钱
            earnTotal = sumPrice.subtract(earn);
            apiAppUserMapper.logAddDiamondBalance(
                    PayLogDTO.builder()
                            .traceId(giftRec.getId())
                            .uid(pid)
                            .changeNum(earn)
                            .serviceTag(
                                    "用户接收礼物-邀请人收益"
                                            + gift.getName()
                                            + "X"
                                            + bo.getNum()
                                            + "-被邀请人:"
                                            + recAppUser.getPlatformId())
                            .logType(PayLogTypeEnums.收益_邀请礼物收益)
                            .build());
        }
        // 加上被赠送人的砖石
        apiAppUserMapper.logAddDiamondBalance(
                PayLogDTO.builder()
                        .traceId(giftRec.getId())
                        .uid(bo.getRecId())
                        .changeNum(earnTotal)
                        .serviceTag(
                                "用户接收礼物"
                                        + gift.getName()
                                        + "X"
                                        + bo.getNum()
                                        + "-赠送人:"
                                        + sendAppUser.getPlatformId())
                        .logType(PayLogTypeEnums.收益_接收礼物)
                        .build());

        AppUserExt sendAppUserExt = appUserExtMapper.selectById(LoginHelper.getUserId());
        // 推送消息日志
        PushMessage.sendTextSingleSysGift(
                recAppUser.getPlatformId(),
                PrivateMsg.builder()
                        .content(
                                BeanUtil.toBean(gift, MsgGift.class).setNum(bo.getNum()).toString())
                        .nickname(sendAppUserExt.getNickName())
                        .headUrl(sendAppUserExt.getHeadUrl())
                        .id(sendAppUserExt.getId())
                        .platformId(sendAppUser.getPlatformId())
                        .build());
        AppUserExt recAppUserExt = appUserExtMapper.selectById(recAppUser.getId());
        // 跑马灯推送
        SpringUtil.publishEvent(
                PushRollingEvent.builder()
                        .type(PushRollingEvent.Type.礼物.getCode())
                        .nickName(sendAppUserExt.getNickName())
                        .headUrl(sendAppUserExt.getHeadUrl())
                        .content(
                                JSONUtil.createObj()
                                        .set("imgUri", gift.getImgUri())
                                        .set("giftName", gift.getName())
                                        .set("recUserNickName", recAppUserExt.getNickName()))
                        .build());
    }

    /**
     * 礼物列表
     *
     * @author 老张
     * @return
     */
    @Override
    public List<Gift> getGiftsList() {
        List<Gift> gifts =
                giftMapper.selectList(
                        Wrappers.lambdaQuery(Gift.class)
                                .select(
                                        Gift::getType,
                                        Gift::getId,
                                        Gift::getPrice,
                                        Gift::getName,
                                        Gift::getImgUri,
                                        Gift::getSvgaUri)
                                .eq(Gift::getValidFlag, EnableEnum.YES.getCode())
                                .eq(Gift::getDelFlag, EnableEnum.NO.getCode())
                                .orderByAsc(Gift::getSortId));
        return gifts;
    }

    /**
     * 礼物墙
     *
     * @author 老张
     * @return
     */
    @Override
    public List<GiftInfoVo> getGiftsWall() {
        // 礼物
        List<GiftInfoVo> giftInfoVos = apiGiftReceiveMapper.countGift(LoginHelper.getUserId());
        return giftInfoVos;
    }
}
